import paho.mqtt.client as mqtt
from django.conf import settings
import random
import time
import json
topic = "BOOK/WS2812B_kz"
# 订阅的 MQTT 主题
MQTT_TOPIC1 = '/writecard'  # 读卡指令的 MQTT 主题
MQTT_TOPIC2 = '/cardID'  # 卡号的 MQTT 主题
class MQTTClient:
    def __init__(self):
        self.client = mqtt.Client()
        # 将回调函数绑定到类方法
        self.client.on_connect = self.on_connect  
        self.client.on_message = self.on_message
        
    # 新增connect方法
    def connect(self):
        # 配置TLS证书
        self.client.tls_set(ca_certs='D:\Codes\ESP-IDF\ESP32S3\comprehensive-course-design\djangoProject\emqxsl-ca.crt')
        # 设置MQTT认证信息
        self.client.username_pw_set(settings.MQTT_USER, settings.MQTT_PASSWORD)
        # 建立连接
        self.client.connect(
            host=settings.MQTT_SERVER,
            port=settings.MQTT_PORT,
            keepalive=settings.MQTT_KEEPALIVE
        )
        # 启动消息循环
        self.client.loop_start()
        
    def on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            print('Connected successfully')
            client.subscribe([
                ('/door', 1),  # 添加门禁主题订阅
                ('/writecard', 1),
                ('/cardID', 1)
            ])
        else:
            print(f'Connection failed with code: {rc}')
            
    def on_message(self, client, userdata, msg):
        print(f"Received `{msg.payload.decode()}` from `{msg.topic}`")
        from back.models import EnvironmentData, CardData  # 保证在方法内部导入
        
        try:
            if msg.topic == MQTT_TOPIC1:
                handle_CardData_data(msg.payload.decode())
            elif msg.topic == MQTT_TOPIC2:
                handle_environment_data(msg.payload.decode())
            else:
                print(f"Unknown topic: {msg.topic}")
        except Exception as e:
            print(f"Error processing message: {e}")  # 移foreign msg reference


def publish(client):
    msg_count = 0
    while True:
        time.sleep(1)
        msg = f"messages: {msg_count}"
        result = client.publish(topic, msg)
        # result: [0, 1]
        status = result[0]
        if status == 0:
            print(f"Send `{msg}` to topic `{topic}`")
        else:
            print(f"Failed to send message to topic {topic}")
        msg_count += 1




# 处理数据
def handle_CardData_data(payload):
    from back.models import EnvironmentData, CardData

    try:
        CardData_data = json.loads(payload)  # 解析收到的 JSON 数据
        id = CardData_data.get('id')  # ID
        species = CardData_data.get('species')  # 获取动物种类

        # 保存动物数据到数据库
        CardData = CardData.objects.create(
            card_number=id,
            information=species,
            
        )
        CardData.save()

        print(f"CardData data saved to database: {CardData}")  # 打印保存成功信息

    except json.JSONDecodeError as e:
        print(f"Error decoding JSON: {e}")  # 解析 JSON 错误打印错误信息
    except Exception as e:
        print(f"Error saving CardData data to database: {e}")  # 保存数据到数据库错误打印错误信息


# 处理读卡数据
def handle_environment_data(payload):
    try:
        env_data = json.loads(payload)
        with transaction.atomic():
            EnvironmentData.objects.update_or_create(
                card_number=env_data['card_id'],
                defaults={
                    'information': f"Lab {env_data['lab_number']} - {env_data['operation']}",
                    'timestamp': env_data.get('timestamp', timezone.now())
                }
            )
    except Exception as e:
        print(f"Error saving card data: {e}")
    except KeyError as e:
        print(f"Missing key in payload: {e}")
    except Exception as e:
        print(f"Database error: {e}")
    except Exception as e:
        print(f"Error saving environment data to database: {e}")  # 保存数据到数据库错误打印错误信息


# 移除模块级别的回调函数赋值
mqtt_client = MQTTClient()
mqtt_client.connect()
